﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Data.OleDb;
using System.Xml;


namespace Searcher
{
    
    public partial class frmFind : Form
    {
        private static readonly String m_PathToSearchCSS = String.Format("file:///{0}/Data/search.css", Application.StartupPath.Replace('\\', '/'));

        private Searcher m_Searcher;
        private Int32 m_PagesCount;

        private Int32 m_DocMaxLines;  // максимальное количество строк на странице документа, если 0, то весь документ
        private Int32 m_SearchMaxLines;  // максиомальное количество строк на странице поиска


        public frmFind()
        {
            InitializeComponent();
        }


        private void SaveSettings()
        {
            XmlDocument doc = new XmlDocument();
            XmlNode root = doc.CreateNode(XmlNodeType.Element, "settings", "");
            doc.AppendChild(root);

            XmlNode node = doc.CreateNode(XmlNodeType.Element, "SearchMaxLines", "");
            XmlAttribute attr = doc.CreateAttribute("value");
            attr.Value = m_SearchMaxLines.ToString();
            node.Attributes.Append(attr);
            root.AppendChild(node);

            node = doc.CreateNode(XmlNodeType.Element, "DocMaxLines", "");
            attr = doc.CreateAttribute("value");
            attr.Value = m_DocMaxLines.ToString();
            node.Attributes.Append(attr);
            root.AppendChild(node);

            doc.Save(Application.StartupPath + @"\config.xml");
        }


        private void LoadSettings()
        {
            if (System.IO.File.Exists(Application.StartupPath + @"\config.xml"))
            {
                XmlTextReader reader = new XmlTextReader(Application.StartupPath + @"\config.xml");
                reader.WhitespaceHandling = WhitespaceHandling.None;
                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element)
                        if ((reader.Name == "SearchMaxLines"))
                        {
                            m_SearchMaxLines = Convert.ToInt32(reader.GetAttribute("value"));
                        }

                    if ((reader.Name == "DocMaxLines"))
                    {
                        m_DocMaxLines = Convert.ToInt32(reader.GetAttribute("value"));
                    }
                }
            }
            else
            {
                MessageBox.Show("Файл '" + Application.StartupPath + @"\config.xml', содержащий настройки, не найден", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                System.Environment.Exit(0);
            }
        }


        private void button2_Click(object sender, EventArgs e)
        {
            List<String> documents = new List<String>(clbDocuments.CheckedItems.Count);
            for (Int32 i = 0; i < clbDocuments.CheckedItems.Count; i++)
            {
                documents.Add(clbDocuments.CheckedItems[i].ToString());
            }

            m_Searcher.Search(tbQuery.Text, (Int32)nudDistance.Value, documents.ToArray());
            StringBuilder webText = new StringBuilder(String.Format("<html><header><style type=\"text/css\">@import \"{0}\";</style></header><body>", m_PathToSearchCSS));
            webText.Append(m_Searcher.GetHtmlResult(0, m_SearchMaxLines - 1));
            m_PagesCount = (Int32)(m_Searcher.GetResultCount() / m_SearchMaxLines) + 1;

            if (m_Searcher.GetResultCount() > m_SearchMaxLines)
            {
                webText.Append(String.Format("<div id=\"page_navigate\"><b>Страница</b>&nbsp;&nbsp;<span class=\"disabled\">предыдущая</span>&nbsp;&nbsp;<b>{0:D}</b>&nbsp;&nbsp;<a href=\"#{1:D}\">следующая</div>", 1, 1));
            }
            else
            {
                if (m_Searcher.GetResultCount() > 0)
                {
                    webText.Append(String.Format("<div id=\"page_navigate\"><b>Страница</b>&nbsp;&nbsp;<span class=\"disabled\">предыдущая</span>&nbsp;&nbsp;<b>{0:D}</b>&nbsp;&nbsp;<span class=\"disabled\">следующая</span></div>", 1));
                }
            }
            webText.Append("</body></html>");

            webBrowser.DocumentText = webText.ToString();
            webBrowser.Select();
        }

        private void splitContainer2_Panel2_Paint(object sender, PaintEventArgs e)
        {

        }

        private void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e)
        {
            String[] data = e.Url.OriginalString.Split('#');
            if (data.Length == 4)
            {
                Int32 doc_id = Convert.ToInt32(data[1]);
                Int32 strBegin;
                if (m_DocMaxLines > 0)
                {
                    strBegin = ((Int32)(Convert.ToInt32(data[2]) / m_DocMaxLines)) * m_DocMaxLines;
                }
                else
                {
                    strBegin = 0;
                }

                frmDocument doc = new frmDocument(m_Searcher, doc_id, strBegin, m_DocMaxLines, Convert.ToInt32(data[2]), Convert.ToInt32(data[3]));
                doc.Show(this);
            }


            if (data.Length == 2)
            {
                Int32 newPageNum = Convert.ToInt32(data[1]);

                StringBuilder webText = new StringBuilder(String.Format("<html><header><style type=\"text/css\">@import \"{0}\";</style></header><body>", m_PathToSearchCSS));
                webText.Append(m_Searcher.GetHtmlResult(newPageNum * m_SearchMaxLines, newPageNum * m_SearchMaxLines + m_SearchMaxLines));

                if (newPageNum > 0)
                {
                    webText.Append(String.Format("<div id=\"page_navigate\"><b>Страница</b>&nbsp;&nbsp;<a href=\"#{1:D}\">предыдущая</a>&nbsp;&nbsp;<b>{0:D}</b>&nbsp;&nbsp;", newPageNum + 1, newPageNum - 1));
                }
                else
                {
                    webText.Append(String.Format("<div id=\"page_navigate\"><b>Страница</b>&nbsp;&nbsp;<span class=\"disabled\">предыдущая</span>&nbsp;&nbsp;<b>{0:D}</b>&nbsp;&nbsp;", newPageNum + 1));
                }

                if (newPageNum < m_PagesCount - 1)
                {
                    webText.Append(String.Format("<a href=\"#{0:D}\">следующая</div>", newPageNum + 1));
                }
                else
                {
                    webText.Append("<span class=\"disabled\">следующая</span></div>");
                }

                webText.Append("</body></html>");
                webBrowser.DocumentText = webText.ToString();
                webBrowser.Select();
            }
        }

        private void tbQuery_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == '\r')
            {
                btFind.PerformClick();
            }
        }

        private void CheckAllDocs(Boolean check)
        {
            for(Int32 i = 0; i < clbDocuments.Items.Count; i++)
            {
                clbDocuments.SetItemChecked(i, check);
            }
        }

        private void frmFind_Load(object sender, EventArgs e)
        {
            LoadSettings();
            String connectionString = String.Format(@"Provider=LCPI.IBProvider;Password='masterkey';User ID=sysdba;Data Source={0}\data\db.fdb", Application.StartupPath);
            String delimiterPath = String.Format(@"{0}\data\delim.csv", Application.StartupPath);
            m_Searcher = new Searcher(connectionString, delimiterPath);
            clbDocuments.Items.AddRange(m_Searcher.GetDocuments().ToArray());
            CheckAllDocs(true);
        }

        private void menuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {

        }

        private void tsmiExit_Click(object sender, EventArgs e)
        {
            Environment.Exit(0);
        }

        private void tsmiPreferences_Click(object sender, EventArgs e)
        {
            frmPreferences preferences = new frmPreferences();
            preferences.MaxDocLines = m_DocMaxLines;
            preferences.MaxSearchLines = m_SearchMaxLines;
            if (preferences.ShowDialog(this) == DialogResult.OK)
            {
                this.m_DocMaxLines = preferences.MaxDocLines;
                this.m_SearchMaxLines = preferences.MaxSearchLines;
                SaveSettings();
            }
        }

        private void tsmiDocView_Click(object sender, EventArgs e)
        {
            frmDocPreview docPreview = new frmDocPreview(m_Searcher);
            if (docPreview.ShowDialog() == DialogResult.OK)
            {
                frmDocument doc = new frmDocument(m_Searcher, docPreview.DocumentID, 0, m_DocMaxLines, -1, -1);
                doc.Show(this);
            }
        }

        private void clbDocuments_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            if (e.CurrentValue == CheckState.Unchecked)
            {
                btFind.Enabled = true;
            }
            else
            {
                if (clbDocuments.CheckedItems.Count > 1)
                {
                    btFind.Enabled = true;
                }
                else
                {
                    btFind.Enabled = false;
                }
            }
            
        }


        private void llbAll_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                CheckAllDocs(true);
            }
        }

        private void llbNothing_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                CheckAllDocs(false);
            }
        }

        private void tsmiDocImport_Click(object sender, EventArgs e)
        {
            frmImport import = new frmImport(m_Searcher);
            if (import.ShowDialog(this) == DialogResult.OK)
            {
                clbDocuments.Items.Clear();
                clbDocuments.Items.AddRange(m_Searcher.GetDocuments().ToArray());
                CheckAllDocs(true);
            }
        }

        private void tsmiDocDelete_Click(object sender, EventArgs e)
        {
            frmDocDelete docDelete = new frmDocDelete();
            docDelete.Documents.Items.AddRange(m_Searcher.GetDocuments().ToArray());
            if (docDelete.ShowDialog(this) == DialogResult.OK)
            {
                if (MessageBox.Show("Вы действительно хотите удалить выбранные документы?", "Удаление документов", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
                {
                    foreach (String doc_name in docDelete.Documents.CheckedItems)
                    {
                        m_Searcher.DeleteDocument(doc_name);
                    }
                }

                clbDocuments.Items.Clear();
                clbDocuments.Items.AddRange(m_Searcher.GetDocuments().ToArray());
                CheckAllDocs(true);

                StringBuilder webText = new StringBuilder(String.Format("<html><header><style type=\"text/css\">@import \"{0}\";</style></header><body>", m_PathToSearchCSS));
                webText.Append(m_Searcher.GetHtmlResult(0, m_SearchMaxLines - 1));
                m_PagesCount = (Int32)(m_Searcher.GetResultCount() / m_SearchMaxLines) + 1;

                if (m_Searcher.GetResultCount() > m_SearchMaxLines)
                {
                    webText.Append(String.Format("<div id=\"page_navigate\"><b>Страница</b>&nbsp;&nbsp;<span class=\"disabled\">предыдущая</span>&nbsp;&nbsp;<b>{0:D}</b>&nbsp;&nbsp;<a href=\"#{1:D}\">следующая</div>", 1, 1));
                }
                else
                {
                    webText.Append(String.Format("<div id=\"page_navigate\"><b>Страница</b>&nbsp;&nbsp;<span class=\"disabled\">предыдущая</span>&nbsp;&nbsp;<b>{0:D}</b>&nbsp;&nbsp;<span class=\"disabled\">следующая</span></div>", 1));
                }
                webText.Append("</body></html>");

                webBrowser.DocumentText = webText.ToString();
                webBrowser.Select();
            }
        }

        private void tsmiAbout_Click(object sender, EventArgs e)
        {
            frmAbout about = new frmAbout();
            about.ShowDialog();
        }

        private void tsmiStatistic_Click(object sender, EventArgs e)
        {
            System.Collections.Hashtable stat = m_Searcher.GetStatistic();
            frmStatistic statistic = new frmStatistic((Int32)stat["DocumentsCount"], (Int32)stat["LinesCount"], (Int32)stat["LexemsCount"], (Int32)stat["WordsCount"]);
            statistic.ShowDialog(this);
        }
    }

}